#pragma once

#include "compiler.hpp"
#include "runner.hpp"
#include "../comm/log.hpp"
#include "../comm/util.hpp"

#include <signal.h>
#include <unistd.h>
#include <jsoncpp/json/json.h>

namespace ns_compileandrun
{
    using namespace ns_util;
    using namespace ns_log;
    using namespace ns_compiler;
    using namespace ns_run;
    class CompileAndRun
    {
    public:
        static void RemoveTempFile(const std::string &file_name)
        {
            std::string _stdin = PathUtil::Stdin(file_name);
            // 删除标准输入文件
            if(FileUtile::IsExist(_stdin))
            {
                unlink(_stdin.c_str());
            }
            // 删除标准输出文件
            std::string _stdout = PathUtil::Stdout(file_name);
            if(FileUtile::IsExist(_stdout))
            {
                unlink(_stdout.c_str());
            }
            // 删除标准错误文件
            std::string _stderr = PathUtil::Stderr(file_name);
            if(FileUtile::IsExist(_stderr))
            {
                unlink(_stderr.c_str());
            }
            // 删除编译错误文件
            std::string _compile_error = PathUtil::CompileError(file_name);
            if(FileUtile::IsExist(_compile_error))
            {
                unlink(_compile_error.c_str());
            }
            // 删除编译生成的可执行文件和源文件
            std::string _exe = PathUtil::Exe(file_name);
            if(FileUtile::IsExist(_exe))
            {
                unlink(_exe.c_str());
            }
            // 删除源文件
            std::string _src = PathUtil::Src(file_name);
            if(FileUtile::IsExist(_src))
            {
                unlink(_src.c_str());
            }
        }
        static std::string CodeToDesc(int code, const std::string &file_name)
        {
            // code > 0 : 进程收到了信号导致异常奔溃
            // code < 0 : 整个过程非运行报错(代码为空，编译报错等)
            // code = 0 : 整个过程全部完成
            std::string desc;
            switch (code)
            {
            case 0:
                desc = "编译运行成功";
                break;
            case -1:
                desc = "提交的代码是空";
                break;
            case -2:
                desc = "未知错误";
                break;
            case -3:
                desc = "代码编译的时候发生了错误";
                break;
            case SIGABRT: // 6
                desc = "内存超过范围";
                break;
            case SIGXCPU: // 24
                desc = "CPU使用超时";
                break;
            case SIGFPE: // 8
                desc = "浮点数溢出";
                break;
            default:
                desc = "未知: " + std::to_string(code);
                break;
            }

            return desc;
        }
        /***************************************
         * 输入:
         * code： 用户提交的代码
         * input: 用户给自己提交的代码对应的输入，不做处理
         * cpu_limit: 时间要求
         * mem_limit: 空间要求
         *
         * 输出:
         * 必填
         * status: 状态码
         * reason: 请求结果
         * 选填：
         * stdout: 我的程序运行完的结果
         * stderr: 我的程序运行完的错误结果
         *
         * 参数：
         * in_json: {"code": "#include...", "input": "","cpu_limit":1, "mem_limit":10240}
         * out_json: {"status":"0", "reason":"","stdout":"","stderr":"",}
         * ************************************/
        static void Start(const std::string& injson,std::string* outjson)
        {
            Json::Value invalue;
            Json::Reader reader;
            reader.parse(injson,invalue);
            std::string code=invalue["code"].asString();
            std::string input=invalue["input"].asString();
            int cpu_limit=invalue["cpu_limit"].asInt();
            int mem_limit=invalue["mem_limit"].asInt();
            int statue_code=0;
            Json::Value out_value;
            int run_result=0;
            std::string file_name;
            file_name=FileUtile::UniqFileName();
            if(code.size()==0)
            {
                statue_code=-1;//代码为空
                goto END;
            }

            if(!FileUtile::WriteFile(PathUtil::Src(file_name),code))
            {
                statue_code=-2;//未知错误
                goto END;
            }
            if(!Compiler::compile(file_name))
            {
                statue_code=-3;//编译错误
                goto END;
            }
            run_result=ns_run::Runner::Run(file_name,cpu_limit,mem_limit);
            if(run_result<0)
            {
                statue_code=-2;//未知错误
            }
            else if(run_result>0)
            {
                statue_code=run_result;//运行错误
            }
            else
            {
                statue_code=0;//运行成功
            }
            END:
            out_value["statue_code"]=statue_code;
            out_value["desc"]=CodeToDesc(statue_code,file_name);
            if(statue_code==0)
            {
               std::string _stdout;
               FileUtile::ReadFile(PathUtil::Stdout(file_name),&_stdout,true);
               out_value["stdout"]=_stdout;
               std::string _stderr; 
               FileUtile::ReadFile(PathUtil::Stderr(file_name),&_stderr,true);
               out_value["stderr"]=_stderr;
            }

            Json::StyledWriter writer;
            *outjson=writer.write(out_value);
            //RemoveTempFile(file_name);
        }
    };
}